// Copyright 2008 Senary
// See credits.txt for details.

// This file is part of Omega VII.

// Omega VII is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Omega VII is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Omega VII.  If not, see <http://www.gnu.org/licenses/>.

#pragma once

#include <string>


#include "Combatunit.h"

// a ship will accelerate even if it does not face its target perfectly.
// This factor determines how much... higher values make it turn longer
// before accelerating. This reduces the sidewards movement of the ship.
const double SHIP_ACCEL_FACTOR = 5.0;

// Ships can fire at their target if the angle towards it does not
// exceed MAX_CANNON_ANGLE.
const double MAX_CANNON_ANGLE = 10.0 / 180.0 * M_PI; // 10?

class Planet;

enum SpaceshipType {
	ST_YATAI_VIII,
	ST_JONTH,
	ST_CYSUS,
	ST_METHI,

	ST_NUMSPACESHIPTYPES
};

enum ModeType {
	MT_IDLE,
	MT_ORBIT,
	MT_MOVE,
	MT_AVOID_PLANET,
	MT_ATTACK_SPACESHIP_FIRE,
	MT_ATTACK_SPACESHIP_TURN,
	MT_ATTACK_PLANET,

	MT_NUMMODETYPES
};

enum TacticType {
	TT_AGRESSIVE,
	TT_PASSIVE,

	TT_NUMTACTICTYPES
};

class Spaceship : public CombatUnit
{
private:
	// Tries to fly towards the target in an intelligent way
	void moveToTarget(float timestep);

protected:
	// Where the spaceship is heading or what it's attacking
	SpaceObject* _target;

	// Current state of the ship (idle, flying, attacking etc.)
	ModeType _mode;

	// Type of the ship. Determines maxSpeed etc.
	SpaceshipType _type;

	// Tactic of the ship. Determines how it responds to an attack etc.
	TacticType _tactic;


public:
	Spaceship(SpaceshipType type);
	~Spaceship(void);
	
	// constant values (depend only on type)
	virtual int maxFirepower() const; // inherited from CombatUnit
	virtual int maxShield() const; // inherited from CombatUnit
	double maxAcceleration(void) const;
	double maxSpeed(void) const;
	int upkeep(void) const;
	int cost(void) const;

	// getter for the type
	SpaceshipType getType() const;

	//operations

	// inherited from CombatUnit
	virtual void attack(CombatUnit* combatUnit, float timestep, float totalTime);

	SpaceObject* getTarget() {return _target;}
	void setTarget(SpaceObject* target);

	// change the tactic
	void setTactic(TacticType tactic);

	// inherited from SpaceObject
	virtual void setOrbitalTarget(SpaceObject* target);

	// Updates position, velocity etc. of the spaceship
	// param timestep: time since the last update, in seconds
	// param totalTime: total time the game has been running
	void update(float timestep, float totalTime);

	// Checks if this spaceship collides with another object
	virtual bool isInRange(SpaceObject const& other) const;

	// Inherited from SpaceObject
	virtual void setOwner(Player * owner);

	// Inherited from CombatUnit
	// Receive a certain amount of damage
	// param damager: the unit that inflicts the damage.
	void receiveDamage(double damage, CombatUnit* damager, float totalTime);

	// Inherited from SpaceObject
	// This method is called when a spaceship died, so others can react
	virtual void somebodyDied(SpaceObject const* who);

	// Convert a string to SpaceshipType
	static SpaceshipType spaceshipTypeFromString(std::string s);

	// Convert a SpaceshipType to string
	static std::string stringFromSpaceshipType(SpaceshipType st);
};
